import Guide from '~/components/layout/guide'
import Snippet from '~/components/snippet'
import { InlineCode } from '~/components/text/code'
import { Image } from '~/components/media'
import Caption from '~/components/text/caption'
import Note from '~/components/text/note'
import Link from '~/components/text/link'
import DeploySection from '~/components/guides/deploy-section'

export const meta = {
  title:
    'Create a Next.js and ButterCMS App That Builds and Deploys with ZEIT Now',
  description:
    'Deploy your Next.js and ButterCMS app with ZEIT Now in a serverless environment.',
  published: '2019-06-21T16:51:04.000Z',
  authors: ['msweeneydev'],
  url: '/guides/deploying-next-and-buttercms-with-now',
  image: `${
    process.env.ASSETS
  }/guides/deploying-next-buttercms-with-now/deploying-next-buttercms-with-now.png`,
  editUrl: 'pages/guides/deploying-next-and-buttercms-with-now.mdx',
  name: 'Next.js + ButterCMS',
  type: 'app',
  lastEdited: '2020-02-04T12:49:00.000Z'
}

In this guide, you will discover how to create a [Next.js](https://nextjs.org/) app that displays links to posts from the [ZEIT blog](/blog) by utilizing the [ButterCMS](https://buttercms.com/) content management system, before deploying **with a single command** to [ZEIT Now](/docs/v2).

[Next.js](https://nextjs.org/) from [ZEIT](https://zeit.co) is a **production-ready framework** that helps you create fast React apps. [ButterCMS](https://buttercms.com/) is a drop-in headless CMS with zero headaches that allows you to **never worry about hosting, upgrades, uptime, security or performance** whilst storing all your content in one place.

By following this guide, you will create a clone of the [example app](https://nextjs-buttercms.now-examples.now.sh/), a starting point to get you up and running with your own Next.js + ButterCMS app in minutes.

<Image
  src={`${
    process.env.ASSETS
  }/guides/deploying-next-buttercms-with-now/deploying-next-buttercms-with-now.png`}
  width={2048 / 2.75}
  height={1170 / 2.75}
  oversize
/>

## Step 1: Create your ButterCMS Content

From your [ButterCMS Collections dashboard](https://buttercms.com/content/collections/), create a new **Collection** called **Posts** by clicking the **+ New Collection** button.

<Image
  src={`${
    process.env.ASSETS
  }/guides/deploying-next-buttercms-with-now/creating-collection.png`}
  width={1555/2}
  height={656/2}
  oversize
  shadow
/>
<Caption>Creating a Collection for your Next.js + ButterCMS project using the ButterCMS Collections dashboard.</Caption>

Add the following fields to your **Collection**, all of type **Short Text**, by clicking the **Add New Property** button:

- `title`
- `date`
- `alt`
- `image`
- `url`

Your **Posts Collection** should look like this:

<Image
  src={`${
    process.env.ASSETS
  }/guides/deploying-next-buttercms-with-now/completed-collection.png`}
  width={1503/2}
  height={592/2}
  oversize
  shadow
/>
<Caption>An example Collection for your Next.js + ButterCMS project.</Caption>

Next, click the **+ Add to Posts** button to create a post, providing the relevant details.

That's it for creating content! You can edit both the **Posts Collection** and its content at any time, either by adding or removing **Posts** or changing the **Collection Item Properties**.

Next, select **Settings** from the account dropdown menu at the top left of the screen. Here you will find your **Read API Token**, make a note of this so you can use it later on in your app.

## Step 2: Creating your Next.js App

Firstly, create a project directory and `cd` into it like so:

<Snippet dark text="mkdir my-nextjs-buttercms-project && cd my-nextjs-buttercms-project" />
<Caption>Creating and entering into the project directory.</Caption>

Next, initialize your project, creating a `package.json` file in the process:

<Snippet dark text="npm init -y" />
<Caption>Initializing your project with a <InlineCode>package.json</InlineCode> file.</Caption>

<Note>
  Using the <InlineCode>-y</InlineCode> flag will initialize the created{' '}
  <InlineCode>package.json</InlineCode> file with{' '}
  <Link href="https://docs.npmjs.com/cli/init">these</Link> default settings.
</Note>

Next, add the project dependencies:

<Snippet dark text="npm i next react react-dom" />
<Caption>Adding <InlineCode>next</InlineCode>, <InlineCode>react</InlineCode> and <InlineCode>react-dom</InlineCode> as dependencies to your project.</Caption>

With the project initialized, create a `/pages` directory with a `index.js` file inside that uses the following code:

```jsx
import { useEffect, useState } from 'react'
import Head from 'next/head'
import Post from '../components/post'

function HomePage() {
  const [posts, setPosts] = useState([])
  useEffect(() => {
    async function getPosts() {
      const res = await fetch(
        `https://api.buttercms.com/v2/content/?keys=posts&auth_token=${
          process.env.API_TOKEN
        }`
      )
      const { data } = await res.json()
      const allPosts = data.posts
      setPosts([...allPosts])
    }
    getPosts()
  }, [])
  return (
    <>
      <Head>
        <title>Next.js + ButterCMS</title>
        <link
          rel="stylesheet"
          href="https://css.zeit.sh/v1.css"
          type="text/css"
        />
      </Head>
      {posts.length > 0
        ? posts.map(p => (
            <Post
              alt={p.alt}
              date={p.date}
              key={p.title}
              image={p.image}
              title={p.title}
              url={p.url}
            />
          ))
        : null}
    </>
  )
}

export default HomePage
```

<Caption>
  An example <InlineCode>index.js</InlineCode> page for your Next.js + ButterCMS
  project.
</Caption>

Let's take look at what this file achieves.

Inside the `useEffect` hook, an asynchronous function, `getPosts`, is defined, this is then called in the `useEffect` hook to retrieve the posts on initial load.

With the posts retrieved, they are then mapped over to be displayed with a `<Post>` component that you will create next.

Create a `/components` directory that contains a `post.js` file with the following content:

```jsx
function Post({ alt, date, image, title, url }) {
  return (
    <div className="container">
      <a href={url}>
        <img alt={alt} src={image} />
      </a>
      <div className="text">
        <h2>{title}</h2>
        <h4>{date}</h4>
      </div>
      <style jsx>{`
        .container {
          cursor: pointer;
          height: 453px;
          margin-bottom: 48px;
        }
        a {
          border-bottom: none;
        }
        a:hover {
          border-bottom: none;
        }
        .text {
          margin-top: -160px;
          padding: 24px;
          position: absolute;
        }
        h2 {
          color: white;
          font-size: 24px;
          margin-bottom: 0;
        }
        h4 {
          color: rgba(255, 255, 255, 0.8);
          font-size: 16px;
          font-weight: 500;
          margin-top: 8px;
        }
      `}</style>
    </div>
  )
}

export default Post
```

<Caption>
  An example <InlineCode>post.js</InlineCode> component for your Next.js +
  ButterCMS project.
</Caption>

Now that your page and component files have been created, the next step will show you how to add an [environment variable](/docs/v2/deployments/environment-variables-and-secrets/) to the project.

## Step 3: Adding an Environment Variable

Add a `now.json` file at the root of your project directory with the following code:

```json
{
  "build": {
    "env": {
      "BUTTER_API_TOKEN": "@butter_api_token"
    }
  }
}
```

<Caption>
  An example <InlineCode>now.json</InlineCode> file for your Next.js + ButterCMS
  project.
</Caption>

With your `now.json` file created, you should add a `next.config.js` file at the root of your project directory with the code below:

```js
module.exports = {
  env: {
    API_TOKEN: process.env.BUTTER_API_TOKEN
  }
}
```

<Caption>
  An example <InlineCode>next.config.js</InlineCode> file for your Next.js +
  ButterCMS project.
</Caption>

The `next.config.js` file provides access to [environment variables](/docs/v2/deployments/environment-variables-and-secrets/) inside your Next.js app.

Now, add the following build script to your `package.json` file:

```json
{
  ...
  "scripts": {
    "build": "next build"
  }
}
```

<Caption>
  Adding a build script to your <InlineCode>package.json</InlineCode> file for
  your Next.js + ButterCMS project.
</Caption>

Next, you will make your API key available to your app during local development by creating a `.env.build` file.

Create a `.env.build` file at the root of your project directory with the following code, adding your API key obtained in [step 1](#step-1:-create-your-buttercms-content) where instructed:

```bash
BUTTER_API_TOKEN=your-api-token
```

<Caption>
  An example <InlineCode>.env.build</InlineCode> file for your Next.js +
  ButterCMS project.
</Caption>

Lastly, to make your API key available for [cloud deployment](/docs/v2/deployments/basics/), create a [Now Secret](/docs/v2/deployments/environment-variables-and-secrets#securing-environment-variables-using-secrets) with the command below:

<Snippet dark text="now secrets add BUTTER_API_TOKEN your-space-id" />
<Caption>
  Adding the <InlineCode>BUTTER_API_TOKEN</InlineCode> secret to your project using <Link href="/docs/v2/deployments/environment-variables-and-secrets#securing-environment-variables-using-secrets">Now Secrets</Link>.
</Caption>

With those steps out the way you are now able to run your app. You can develop your app locally using the following command:

<Snippet dark text="next dev" />
<Caption>
  Using the <InlineCode>next dev</InlineCode> command to run the app locally.
</Caption>

## Step 4: Deploying the App

<DeploySection meta={meta} />

export default ({ children }) => <Guide meta={meta}>{children}</Guide>

export const config = {
  amp: 'hybrid'
}
